#pragma once

#include <chrono>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <bitset>
#include <iomanip>
#include <iostream>

#ifdef _WIN32
//#include <winsock.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif // !M_PI
#else
#include <arpa/inet.h>
#endif

#if defined(_WIN32)
// inline uint64_t htonll(uint64_t value)
// {
//     int32_t high_part = htonl(static_cast<uint32_t>(value >> 32));
//     int32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL));
//     return (static_cast<uint64_t>(low_part) << 32) | high_part;
// }
// inline uint64_t ntohll(uint64_t value)
// {
//     return htonll(value);
// }
#else
inline uint64_t htonll(uint64_t x) { return htobe64(x); }
inline uint64_t ntohll(uint64_t x) { return be64toh(x); }
#endif

#ifdef _WIN32
#ifdef ISCLIBLIDAR_EXPORTS
#define ISCLIBLIDAR_API __declspec(dllexport)
#elif defined(DEMO_BUILD)
#define ISCLIBLIDAR_API  // 在demo模式下不使用导入/导出
#else
#define ISCLIBLIDAR_API __declspec(dllimport)
#endif
#else
#define ISCLIBLIDAR_API
#endif

struct Point
{
    double x;
    double y;
    int index;

    Point operator+(const Point &other) const
    {
        return {x+other.x,y+other.y,0};
    }

    Point operator-(const Point &other) const
    {
        return {x-other.x,y-other.y,0};
    }
};

struct Line
{
    double slope;
    double intercept;
};

struct Segment
{
    Line line;
    Point start;
    Point end;
};

class ISCLIBLIDAR_API Utils
{
public:
    /// @brief 时间戳转日期时间字符串
    /// @param timestamp 时间戳
    /// @return 日期时间字符串
    static std::string TimeStamp2DateTimeString(double timestamp);

    /// @brief 日期时间字符串转时间戳
    /// @param datetime 日期时间字符串
    /// @return 时间戳
    static double DateTimeString2TimeStamp(std::string &datetime);

    /// @brief 寻找目录下符合时间戳范围的文件
    /// @param dir_path 目录路径
    /// @param start_time_stamp 开始时间戳-秒级
    /// @param end_time_stamp 结束时间戳-秒级
    /// @return 文件路径列表
    static std::vector<std::string> FindRelevantFiles(const std::string &dir_path, double start_time_stamp, double end_time_stamp);

    /// @brief 度转弧度
    /// @param d 度
    /// @return 弧度
    static double Rad(double d);

    /// @brief 多边形拟合
    /// @param points 点集
    /// @param torerance 容差
    /// @param min_points 最小点数
    /// @return 直线
    static Line Ransac(const std::vector<Point> &points, double torerance, int min_points);

    /// @brief 多边形拟合
    /// @param points 点集
    /// @param torerance 容差
    /// @param min_points 最小点数
    /// @return 多段线线方程，有序
    static std::vector<Segment> RansacPoly(const std::vector<Point> &points, double torerance, int min_points);

    /// @brief 计算直线交点
    /// @param line1 直线1
    /// @param line2 直线2
    /// @return 交点
    static Point CalculateIntersection(const Line &line1, const Line &line2);

    /// @brief 点是否在线段上
    /// @param p 点
    /// @param origin 射线起点
    /// @param direct 指向的方向点
    /// @return 是否在线段上
    static bool IsPointOnRay(Point p, Point origin, Point direct);

    /// @brief 打印二进制
    /// @param value 值
    static void printBinary(uint64_t value);
};